﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Net;

namespace GShare1._0.Server
{

    public partial class GUI_Server : Form
    {
        MainThreadInvoker mainInvoker;
        MessageBoxInvoker mboxInvoker;
        public Server Server;
        ClientListUpdateDelegate listInvoker;
        public GUI_Server()
        {
            mboxInvoker = new MessageBoxInvoker(MboxInvoker);
            mainInvoker = new MainThreadInvoker(Invoker);
            listInvoker = new ClientListUpdateDelegate(ListUpdater);

            InitializeComponent();
            //label1.Text = GetExternalIP().ToString();
        }

        private void Invoker(Delegate MI)
        {
            //MethodInvoker invoke = new MethodInvoker(delegate
            //    {
            //        MessageBox.Show(msg);
            //    });
            BeginInvoke(MI);
        }

        private void ListUpdater(List<Client> clientList)
        {
            MethodInvoker invoker = new MethodInvoker(delegate
                {

                    listviewClientList.Items.Clear();
                    if (clientList.Count != 0)
                    {
                        
                        foreach (Client client in clientList.ToArray())
                        {
                            ListViewItem clientItem = new ListViewItem(client.ClientInfo.UserName);
                            clientItem.SubItems.Add(client.ClientSocket.RemoteEndPoint.ToString());
                            //clientItem.SubItems.Add(client.AdminUser.ToString());
                            clientItem.SubItems.Add(client.ClientInfo.ConnectionTime.ToString());
                            clientItem.Tag = client;
                            listviewClientList.Items.Add(clientItem);
                        }
                    }
                    UpdateRoomDisplay();
                });
            BeginInvoke(invoker);




        }



        private void MboxInvoker(string msg)
        {
            MethodInvoker del = delegate
                {
                    textBoxServerChat.Text += msg + Environment.NewLine;
                };
            //Invoke this on main thread - Here we decide where to invoke could just run here
            BeginInvoke(del);
        }



        private void button1_Click_1(object sender, EventArgs e)
        {
            if (Server == null)
            {
                Server = new Server(mboxInvoker, listInvoker,mainInvoker);
                Server.Start();
            }
            else
            {
                MessageBox.Show("Server Already Running");
            }
            
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (Server != null)
            {
                Server.Shutdown();
                Server = null;
                
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            if (listviewClientList.SelectedItems.Count != 0)
            {
                //Get the selected client from the list and kick
                Client client = (Client)listviewClientList.SelectedItems[0].Tag;
                client.Disconnect();

            }
        }

        private void buttonServerSendMessage_Click(object sender, EventArgs e)
        {
            Server.Message("Server: "+textBoxServerSendMessage.Text);
            mboxInvoker.BeginInvoke("Server: " + textBoxServerSendMessage.Text,null,null);
        }

        public void UpdateRoomDisplay()
        {
            treeViewRoom.Nodes.Clear();
            TreeNode serverNode = new TreeNode(Server.ServerRoom.Name);
            serverNode.Tag = Server.ServerRoom;
            serverNode.ContextMenuStrip = contextMenuStripRoom;
            treeViewRoom.Nodes.Add(serverNode);

            //use server room object to create the treeView
             foreach (Client client in Server.ServerRoom.ClientList)
            {
                TreeNode treeNode = new TreeNode(client.ClientInfo.UserName);
                treeNode.Tag = client;
                treeNode.ContextMenuStrip = contextMenuStripClient;
                treeViewRoom.Nodes[0].Nodes.Add(treeNode);
            }
            foreach (Room room in Server.ServerRoom.Rooms)
            {
                TreeNode roomNode = new TreeNode(room.Name);
                roomNode.Tag = room;
                roomNode.ContextMenuStrip = contextMenuStripRoom;
                populateRooms(room,ref roomNode);
                treeViewRoom.Nodes[0].Nodes.Add(roomNode);
            }
            treeViewRoom.ExpandAll();
            
        }

        public void populateRooms(Room room,ref TreeNode treeNode)
        {
            //populate clients within the room
            foreach (Client client in room.ClientList)
            {
                TreeNode clientNode = new TreeNode(client.ClientInfo.UserName);
                clientNode.Tag = client;
                clientNode.ContextMenuStrip = contextMenuStripClient;
                treeNode.Nodes.Add(clientNode);
            }

            //check if room count is more than 1
            if (room.ChildRooms.Count != 0)
            {
                
                //Populate Child Rooms
                foreach (Room roomItem in room.ChildRooms)
                {
                    TreeNode roomNode = new TreeNode(roomItem.Name);
                    roomNode.Tag = roomItem;
                    roomNode.ContextMenuStrip = contextMenuStripRoom;
                    treeNode.Nodes.Add(roomNode);
                    populateRooms(roomItem,ref roomNode);

                }
            }
            
        }

        private void button1_Click(object sender, EventArgs e)
        {
            
        }

        private void toolStripMenuItemAddRoom_Click(object sender, EventArgs e)
        {

            GUI_AddRoom addRoomForm = new GUI_AddRoom();
            //get the treeNodes Tag
            TreeNode treeNode = treeViewRoom.SelectedNode;
            if (treeNode.Tag.GetType() == typeof(ServerRoom))
            {
                //Create new Room
                addRoomForm.ShowDialog();
                if (addRoomForm.dataCollected)
                {
                    Room room = new Room(addRoomForm.Name, addRoomForm.NumberOfUsers, addRoomForm.Private, null, addRoomForm.Password);
                    Server.ServerRoom.AddRoom(room);
                    //call update
                    UpdateRoomDisplay();
                }
                

               
            }
            if (treeNode.Tag.GetType() == typeof(Room))
            {
                Room room = (Room)treeNode.Tag;
                //Create new Room
                addRoomForm.ShowDialog();
                if (addRoomForm.dataCollected)
                {
                    Room newRoom = new Room(addRoomForm.Name, addRoomForm.NumberOfUsers, addRoomForm.Private, null, addRoomForm.Password);
                    room.AddRoom(newRoom);
                    //call update
                    UpdateRoomDisplay();
                }
               
                

                
            }

            
        }

        private void clientInfoToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TreeNode treeNode = treeViewRoom.SelectedNode;
            if (treeNode.Tag.GetType() == typeof(Client))
            {
                Client client = (Client)treeNode.Tag;
                GUI_ClientInfo clientInfoForm = new GUI_ClientInfo(client.ClientInfo);
                clientInfoForm.Show();
            }

        }

        private void renameToolStripMenuItem_Click(object sender, EventArgs e)
        {
            TreeNode treeNode = treeViewRoom.SelectedNode;
            if (treeNode.Tag.GetType() == typeof(Room))
            {
                Room room = (Room)treeNode.Tag;
                GUI_RenameRoom renameForm = new GUI_RenameRoom();
                renameForm.ShowDialog();
                if (renameForm.complete) room.Rename(renameForm.Name);
                UpdateRoomDisplay();
            }
            if (treeNode.Tag.GetType() == typeof(ServerRoom))
            {
                ServerRoom room = (ServerRoom)treeNode.Tag;
                GUI_RenameRoom renameForm = new GUI_RenameRoom();
                renameForm.ShowDialog();
                if (renameForm.complete) room.Name = renameForm.Name;
                UpdateRoomDisplay();
            }

        }


    }
}
